<template>
  <canvas ref="bjsCanvas" class="full-screen"></canvas>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import * as BABYLON from '@babylonjs/core';
import "@babylonjs/gui";
import '@babylonjs/loaders';

const bjsCanvas = ref(null);
let engine = null;
let scene = null;
let mat = null;
// 精确心形模型
const createAccurateHeart = () => {
  const heartShape = [];
  for (let theta = 0; theta < 2 * Math.PI; theta += 0.01) {
    const x = 16 * Math.pow(Math.sin(theta), 3);//三次方
    const y = 13 * Math.cos(theta) -
        5 * Math.cos(2*theta) -
        2 * Math.cos(3*theta) -
        Math.cos(4*theta);
    heartShape.push(new BABYLON.Vector3(x/20, y/20, 0));
  }

  const heart = BABYLON.MeshBuilder.CreateLathe("heart", {
    shape: heartShape,
    sideOrientation: BABYLON.Mesh.DOUBLESIDE,//双面
    tessellation: 64//力度
  });
  heart.position.y=-1;

  // // 心形材质
  const heartMat = new BABYLON.StandardMaterial("heartMat", scene);
  heartMat.diffuseColor = new BABYLON.Color3(1, 0.2, 0.3);
  // heartMat.emissiveColor = new BABYLON.Color3(1, 0.5, 0.5);
  heartMat.specularPower = 32;
  heartMat.alpha = 1;//透明0-1

  // 动态纹理
  // const noiseTexture = new BABYLON.NoiseProceduralTexture("noise", 256, scene);
  // noiseTexture.animationSpeedFactor = 0.5;
  //
  // heartMat.opacityTexture = noiseTexture;
  //
  heart.material = heartMat;



  return heart;
};

// 心跳动画
const createHeartAnimation = (mesh) => {
  const animationGroup = new BABYLON.AnimationGroup("heartAnimation");

  // 缩放动画
  const scaleAnim = new BABYLON.Animation(
      "scaleAnim",
      "scaling",
      60,
      BABYLON.Animation.ANIMATIONTYPE_VECTOR3,//向量类型
      BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE//循环
  );

  const scaleKeys = [
    { frame: 0, value: new BABYLON.Vector3(1, 1, 1) },
    { frame: 10, value: new BABYLON.Vector3(1.3, 1.3, 1.3) },
    //缩小
    { frame: 20, value: new BABYLON.Vector3(0.9, 0.9, 0.9) },
    //放大
    { frame: 30, value: new BABYLON.Vector3(1.2, 1.2, 1.2) },
    { frame: 40, value: new BABYLON.Vector3(1, 1, 1) }
  ];
  scaleAnim.setKeys(scaleKeys);



  animationGroup.addTargetedAnimation(scaleAnim, mesh);

   animationGroup.play(true);
};


// 流星效果
const createMeteorEffect = () => {
  const particleSystem = new BABYLON.ParticleSystem("particles", 2000, scene);
  particleSystem.particleTexture = new BABYLON.Texture("https://assets.babylonjs.com/textures/flare.png");  // 粒子贴图

  particleSystem.minSize = 0.1;  // 最小尺寸
  particleSystem.maxSize = 0.5;  // 最大尺寸
  particleSystem.minLifeTime = 1.5;  // 最短存活时间（秒）
  particleSystem.maxLifeTime = 3;  // 最长存活时间
  particleSystem.emitRate = 80;  // 每秒发射80个粒子

  // // 运动方向（左右扩散）
  particleSystem.direction1 = new BABYLON.Vector3(-5, 5, 0);
  particleSystem.direction2 = new BABYLON.Vector3(5, 5, 0);

  particleSystem.gravity = new BABYLON.Vector3(0, -10, 0);  // 向下重力（模拟抛物线）

  // 颜色渐变（白→淡蓝）
  particleSystem.color1 = new BABYLON.Color4(1, 1, 1, 1);
  particleSystem.color2 = new BABYLON.Color4(0.8, 0.8, 1, 1);

  particleSystem.blendMode = BABYLON.ParticleSystem.BLENDMODE_ONEONE;  // 混合模式（发光效果）

  particleSystem.start();  // 启动粒子系统
};

// 初始化场景
const initScene = () => {
  scene = new BABYLON.Scene(engine);

  // 相机设置
  const camera = new BABYLON.ArcRotateCamera(
      "camera",
      Math.PI / 2,
      Math.PI / 3,
      8,
      BABYLON.Vector3.Zero(),
      scene
  );
  camera.attachControl(bjsCanvas.value, true);
  camera.lowerBetaLimit = Math.PI / 4;
  camera.upperBetaLimit = Math.PI / 2.2;

  new BABYLON.HemisphericLight("ambient", new BABYLON.Vector3(0, 1, 0), scene);

  // 添加辉光
  // new BABYLON.GlowLayer("glow", scene).intensity = 1;

  return scene;
};

onMounted(() => {
  engine = new BABYLON.Engine(bjsCanvas.value, true);
  scene = initScene();

  const heart = createAccurateHeart();
  createHeartAnimation(heart);
  createMeteorEffect();
  scene.registerBeforeRender(() => {

  });

  engine.runRenderLoop(() => {
    scene.render();
  });

  window.addEventListener("resize", () => {
    engine.resize();
  });
});

onBeforeUnmount(() => {
  engine.dispose();
});
</script>

<style>
.full-screen {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  touch-action: none;
  outline: none;
}
</style>